package codec

import (
	"gitee.com/yanwc/ebicycle/device/frame"
	"gitee.com/yanwc/ebicycle/device/internal/field"
	"gitee.com/yanwc/ebicycle/device/utils"

	gerrors "github.com/panjf2000/gnet/pkg/errors"
)

var Tag frame.FrameTag = 0xAA55 // 标识数据包的开始

// 帧协议
type Frame struct {
	CmdWord field.CommandWord   // 命令字
	SN      field.SerialNumber  // 序号
	Length  field.ContentLength // 长度
	rawData []byte              // 原始数据帧
}

var _ frame.IFrame = (*Frame)(nil)

func NewEmptyFrame(cmdWord field.CommandWord, sn field.SerialNumber) *Frame {
	return &Frame{
		CmdWord: cmdWord,
		SN:      sn,
	}
}

func (fc *Frame) WrapPacket(data []byte) (out []byte) {
	out = append([]byte{}, utils.NumberToBytesWithBigEndian(Tag)...)
	out = append(out, fc.CmdWord[:]...)
	out = append(out, fc.SN[:]...)
	out = append(out, utils.NumberToBytesWithBigEndian(uint16(len(data)))...)
	out = append(out, data...)
	return
}

func (fc *Frame) UnWrapPacket(data []byte) (err error) {
	if len(data) < 4 {
		return gerrors.ErrIncompletePacket
	}

	var cmdWord field.CommandWord
	var sn field.SerialNumber
	var length field.ContentLength
	utils.LoadPacket(data, cmdWord[:], sn[:], length[:])
	fc.CmdWord = cmdWord
	fc.SN = sn
	fc.Length = length
	fc.rawData = data
	return
}

func (fc *Frame) RawData() []byte {
	return fc.rawData
}

func (fc *Frame) PayloadData() []byte {
	startIndex := len(fc.CmdWord) + len(fc.SN) + len(fc.Length)
	endIndex := startIndex + len(fc.Length)
	return fc.rawData[startIndex:endIndex]
}

func (fc *Frame) GetSN() field.SerialNumber {
	return fc.SN
}

func (fc *Frame) GetCmdWord() field.CommandWord {
	return fc.CmdWord
}

func (fc *Frame) CRCCheck() bool {
	return true
}
